home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
jwpsrc.zip
/
FILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-31
|
72KB
|
2,509 lines
/* Copyright (C) Stephen Chung, 1991-1993. All rights reserved. */
#include "jwp.h"
#include "idm.h"
#include <math.h>
/* Font Width tables */
static int SystemWT[256];
static int AsciiWT[256];
static int AsciiErrors[256];
#define FIRSTBLOCKSIZE sizeof(PARAGRAPH) /* So we can reuse the block */
#define CARETWIDTH 2
#define DELAYCARET(x) { delay = CaretDelayed; CaretDelayed = x; }
#define RESTORECARET() { CaretDelayed = delay; }
#define THERULER(x) ((RULER(x).hwnd == NULL) ? 0 : RULERHEIGHT)
extern BOOL FAR PASCAL KanjiInfoProc (HWND, WORD, WORD, LONG);
extern BOOL FAR PASCAL JISInputProc (HWND, WORD, WORD, LONG);
extern BOOL FAR PASCAL LookupProc (HWND, WORD, WORD, LONG);
extern BOOL FAR PASCAL JISTableDlgProc (HWND, WORD, WORD, LONG);
/* Mouse-related statics */
static BOOL CaretDelayed = FALSE;
static BOOL capturing = FALSE;
static BOOL MouseActivated = FALSE;
static POINT LastSeen;
static HWND PrevWindow = NULL;
void SwitchMenu (int menu) /* 0 = full, 1 = minimal */
{
static int curmenu = -1;
extern HMENU FullMenu, MinimalMenu;
if (menu == curmenu) return;
switch (menu) {
case 0: SetMenu(global.hwnd, FullMenu); hmenu = FullMenu; break;
case 1: SetMenu(global.hwnd, MinimalMenu); hmenu = MinimalMenu; break;
default: return;
}
curmenu = menu;
ProcessMenuTexts();
UpdateQuickFiles();
}
void CloseFile (FILEOPTIONS *f)
{
PARAGRAPH far *p, far *p2;
ONELINE far *lp1, far *lp2;
TakeCareOfThings(f, TRUE);
for (p = f->paragraph; p != NULL; ) {
for (lp1 = p->lines; lp1 != NULL; ) {
lp2 = lp1;
lp1 = lp1->next;
FreeStruct(lp2);
}
FreeBlock(p->text);
p2 = p->next;
FreeStruct(p);
p = p2;
}
FreeUndoChain(f->undo);
FreeUndoChain(f->redo);
}
BOOL Skip (POSITION *p, int n)
{
if (n > 0) {
for(; n > 0; n--) {
if (p->line->next == NULL) {
if (p->para->next == NULL) return (FALSE);
p->para = p->para->next;
p->line = p->para->lines;
} else {
p->line = p->line->next;
}
}
} else {
for (; n < 0; n++) {
if (p->line->prev == NULL) {
if (p->para->prev == NULL) return (FALSE);
p->para = p->para->prev;
p->line = p->para->lastline;
} else {
p->line = p->line->prev;
}
}
}
p->pos = 0;
return (TRUE);
}
void DoCaret (FILEOPTIONS *f, int x, int y, BOOL on)
{
if (on) {
if (!CaretDelayed) {
if (!f->caret) {
SetCaretPos((x > CARETWIDTH) ? x - CARETWIDTH / 2: x, y - LINEGAP(f)/2);
ShowCaret(f->hwnd);
f->caret = TRUE;
} else {
SetCaretPos((x > CARETWIDTH) ? x - CARETWIDTH / 2: x, y - LINEGAP(f)/2);
}
}
} else {
if (f->caret) {
HideCaret(f->hwnd);
f->caret = FALSE;
}
}
}
/* Width Table: 0 = System font, 1 = ASCII font, -1 = reload ASCII, -2 = reload all */
int FontCharWidth (int ch, int WidthTable)
{
int i, width;
double ratio;
HDC hdc;
HFONT hfont;
switch (WidthTable) {
case -2:
hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
SelectObject(hdc, SYSTEM_FONT);
GetCharWidth(hdc, 0, 255, SystemWT);
DeleteDC(hdc);
/* falls into next case... */
case -1:
hdc = GetPrinterDC(TRUE, NULL);
if (hdc == NULL) hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
hfont = SelectAsciiFont(hdc, DefAsciiFont.facename, DefAsciiFont.size, NULL);
SelectObject(hdc, hfont);
if (!GetCharWidth(hdc, 0, 255, AsciiWT)) {
ErrorMessage(global.hwnd, "WARNING: Cannot get font width table from the printer driver. "
"Formatting may be messed up.");
DeleteDC(hdc);
DeleteObject(hfont);
hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
hfont = SelectAsciiFont(hdc, DefAsciiFont.facename, DefAsciiFont.size, NULL);
SelectObject(hdc, hfont);
GetCharWidth(hdc, 0, 255, AsciiWT);
DeleteDC(hdc);
DeleteObject(hfont);
} else {
DeleteDC(hdc);
DeleteObject(hfont);
}
ratio = (double) global.resolution.y / (double) global.resolution.x;
ratio *= global.dispscale / global.printscale;
for (i = 0; i <= 255; i++) {
width = AsciiWT[i] * 10;
width = (int) floor((double) width * ratio + 0.5);
AsciiWT[i] = width / 10;
AsciiErrors[i] = width % 10;
if (AsciiErrors[i] > 0) {
AsciiWT[i]++;
AsciiErrors[i] = 10 - AsciiErrors[i];
}
}
return (0);
case 0:
return (SystemWT[ch]);
case 1:
return (AsciiWT[ch]);
}
return (0);
}
#ifdef FASTCOMPUTER
int FontDisplayError (int ch, PARAGRAPH far *pp, ONELINE far *lp)
{
if (AsciiErrors[ch] == 0) return (0);
else if (AsciiErrors[ch] == 9) return (1);
else {
int i, n;
for (i = n = 0; i < lp->length; i++) if (pp->text[lp->position + i].kanji == ch) n++;
if (AsciiErrors[ch] > 0 && n % (10 - AsciiErrors[ch]) == 0) return (1);
return (0);
}
}
#else
int FontDisplayError (int ch, int pos)
{
if (AsciiErrors[ch] > 0 && pos % (10 - AsciiErrors[ch]) == 0) return (1);
return (0);
}
#endif FASTCOMPUTER
DWORD GetDimension (FILEOPTIONS *f, POSITION p, int x)
{
DWORD dimension;
BYTE ch;
if (KANJIPOS(p)) {
dimension = MAKELONG(f->basefont->width, f->basefont->height);
return (dimension);
}
ch = CHAROF(p, POSOF(p));
if (!ch) {
dimension = MAKELONG(0, f->basefont->height);
return (dimension);
} else if (ch == '\t') {
if (x < 0) {
dimension = (-x) % BASEWIDTH(f);
if (dimension == 0) dimension = BASEWIDTH(f);
} else {
dimension = BASEWIDTH(f) - (x % BASEWIDTH(f));
}
dimension = MAKELONG(dimension, f->basefont->height);
} else {
if (ch < ' ') ch = (global.draftview ? global.textmetric.tmDefaultChar : DefAsciiFont.textmetric.tmDefaultChar);
if (global.draftview || !(f->type & FN_NORMAL)) {
dimension = MAKELONG(FontCharWidth(ch, 0), AVGHEIGHT);
} else {
int width;
//width = FontCharWidth(ch,1) - FontDisplayError(ch, PARAOF(p), LINEOF(p));
width = FontCharWidth(ch,1) - FontDisplayError(ch, POSOF(p));
dimension = MAKELONG(width, DefAsciiFont.textmetric.tmHeight);
}
}
return (dimension);
}
void FillCPos (FILEOPTIONS *f, PARAGRAPH far *para, int from, int to)
{
int i, j, k, abspos, len;
int limit = C64K / sizeof(POINT);
unsigned int cpossize;
POSITION p;
UNIT far *cp;
/* Check the size of array */
len = unitlen(para->text);
cpossize = (len * sizeof(POINT)) / CPOSPAGESIZE;
cpossize = (cpossize + 1) * CPOSPAGESIZE;
if (cpossize > C64K) {
ErrorMessage(global.hwnd, "Warning! Too many characters in the paragraph!!!");
return;
}
if (global.cpossize != cpossize) {
global.cpos = (POINT far *) BlockRealloc(global.cpos, cpossize);
global.cpossize = cpossize;
}
for (i = from, cp = para->text + from; ; cp++, i++) {
if (i >= limit) {
ErrorMessage(global.hwnd, "Too many characters in a paragraph!");
break;
}
if (to >= 0 && i > to) break;
global.cpos[i].x = -1;
global.cpos[i].y = -1;
if (!cp->kanji) break;
}
global.cposcount = i + 1;
p = f->top;
j = LINEGAP(f);
do {
j += LINEOF(p)->height;
if (j > f->height) break;
if (PARAOF(p) != para) {
j += PARAOF(p)->spacing;
continue;
}
i = LEFTMARGIN(p) * BASEWIDTH(f) - f->startx;
for (k = 0; k <= LINEOF(p)->length; k++) {
POSOF(p) = k;
abspos = POS2ABS(p);
if (abspos < from || (to >= 0 && abspos > to)) continue;
global.cpos[abspos].x = i;
global.cpos[abspos].y = j;
if (k < LINEOF(p)->length) {
i += LOWORD(GetDimension(f, p, i));
if (CHAROF(p, POSOF(p)) == '\n') {
/* Nothing */
} else if (CHAROF(p, POSOF(p)) != '\t') {
if (KANJIPOS(p) || (POSOF(p) < LINEOF(p)->length - 1 && KANJIAT(p,POSOF(p)+1)))
i += f->leading;
}
}
}
j += PARAOF(p)->spacing;
} while (NEXTLINE(p));
global.cpospara = para;
}
static void ShiftCPos(FILEOPTIONS *f, int dx, int dy)
{
int i;
for (i = 0; i < global.cposcount; i++) {
if (global.cpos[i].x >= 0) global.cpos[i].x += dx;
if (global.cpos[i].y >= 0) global.cpos[i].y += dy;
if (global.cpos[i].y < 0 || global.cpos[i].y > f->height)
global.cpos[i].y = -1;
}
}
int CalcLength (FILEOPTIONS *f, POSITION *pos)
{
int i;
POSITION p = *pos;
for (i = POSOF(p) = 0; POSOF(p) < POSOF(*pos); POSOF(p)++) {
i += LOWORD(GetDimension(f, p, i));
if (CHAROF(p, POSOF(p)) == '\n') {
/* Nothing */
} else if (CHAROF(p, POSOF(p)) != '\t') {
if (KANJIPOS(p) || (POSOF(p) < LINEOF(p)->length - 1 && KANJIAT(p,POSOF(p)+1)))
i += f->leading;
}
}
return (i + BASEWIDTH(f) * LEFTMARGIN(p));
}
static BOOL MatchPseudo(FILEOPTIONS *f, BOOL horizontal, BOOL CanHaveNoMatch)
{
int i, j, k, w;
POSITION p = f->current;
if (horizontal) {
for(POSOF(p) = 0, i = BASEWIDTH(f) * LEFTMARGIN(p) - f->startx;
POSOF(p) < CURLINE(f)->length && i <= PSEUDOX(f); POSOF(p)++) {
i += LOWORD(GetDimension(f, p, i));
if (CHAROF(p, POSOF(p)) != '\t') {
if (KANJIPOS(p) || (POSOF(p) < LINEOF(p)->length - 1 && KANJIAT(p,POSOF(p)+1)))
i += f->leading;
}
}
if (POSOF(p) > 0 && (POSOF(p) < LINEOF(p)->length || i > PSEUDOX(f))) {
POSOF(p)--;
w = LOWORD(GetDimension(f, p, i)); /* Char width */
if (CHAROF(p, POSOF(p)) != '\t') {
if (KANJIPOS(p) || (POSOF(p) < LINEOF(p)->length - 1 && KANJIAT(p,POSOF(p)+1)))
w += f->leading;
}
if (i >= PSEUDOX(f) + (w / 2)) {
i -= w;
} else {
POSOF(p)++;
}
}
if (i < 0 || i >= f->width) {
i += f->startx;
if (i >= f->width) {
/* Move it to the middle */
k = (i - (f->width / 3)) / BASEWIDTH(f);
f->startx = k * BASEWIDTH(f);
CURX(f) = i - f->startx;
} else {
f->startx = 0;
CURX(f) = i;
}
SetHorzScroll(f);
CURCHAR(f) = POSOF(p);
FillCPos(f, CURPARA(f), 0, -1);
InvalidateRect(f->hwnd, NULL, TRUE);
UpdateWindow(f->hwnd);
return (TRUE);
}
CURX(f) = i;
CURCHAR(f) = POSOF(p);
return (TRUE);
} else {
p = f->top;
j = LINEGAP(f); /* Vertical height */
for (;;) {
j += LINEOF(p)->height;
if (j >= PSEUDOY(f)) break;
if (!NEXTLINE(p)) break;
j += PARAOF(p)->spacing;
}
if (j >= PSEUDOY(f) || !CanHaveNoMatch) {
f->current = p;
CURY(f) = j;
return (TRUE);
} else {
return (FALSE);
}
}
}
BOOL FindCaret (FILEOPTIONS *f, BOOL LongMethod)
{
int i, j, k;
POSITION p;
if (!LongMethod) {
if (global.cpospara != CURPARA(f)) FillCPos(f, CURPARA(f), 0, -1);
i = POS2ABS(f->current);
if (CURCHAR(f) >= CURLINE(f)->length) {
CURX(f) = CURLINE(f)->width - f->startx;
if (CURX(f) < 0 || CURX(f) >= f->width) CURX(f) = -1;
if (CURLINE(f)->length > 0) i--;
CURY(f) = global.cpos[i].y;
} else {
CURX(f) = global.cpos[i].x;
CURY(f) = global.cpos[i].y;
}
return (CURX(f) >= 0 && CURY(f) >= 0 &&
CURX(f) < f->width && CURY(f) < f->height);
} else {
p = f->top;
j = LINEGAP(f); /* Vertical position */
do {
j += LINEOF(p)->height;
if (j > f->height) return (FALSE);
if (LINEOF(p) == CURLINE(f)) {
k = CalcLength(f, &(f->current)) - f->startx;
if (k < 0 || k >= f->width) break;
CURX(f) = k;
CURY(f) = j;
return (TRUE);
}
j += PARAOF(p)->spacing;
} while (NEXTLINE(p));
return (FALSE);
}
}
void FindScrollPos(FILEOPTIONS *f)
{
POSITION p;
if (f->type & FN_NOSCROLLBARS) return;
PARAOF(p) = f->paragraph;
LINEOF(p) = PARAOF(p)->lines;
f->vscroll = 0;
do {
if (PARAOF(p) == CURPARA(f) && LINEOF(p) == CURLINE(f)) break;
(f->vscroll)++;
} while (NEXTLINE(p));
}
void SetHorzScroll(FILEOPTIONS *f)
{
if (f->startx < 0) f->startx = 0;
if (!(f->type & FN_NORMAL) || (f->type & FN_NOSCROLLBARS)) return;
if (f->startx < (f->linelen * BASEWIDTH(f))) {
SetScrollPos(f->parent, SB_HORZ, f->startx / BASEWIDTH(f), TRUE);
} else {
SetScrollPos(f->parent, SB_HORZ, f->linelen, TRUE);
}
}
void MoveIntoWindow (FILEOPTIONS *f)
{
BOOL inside;
POSITION p;
int i, j;
/* Line within window? */
p = f->top;
j = LINEGAP(f);
inside = FALSE;
do {
j += LINEOF(p)->height;
if (j + LINEGAP(f) > f->height) {
break;
} else if (LINEOF(p) == CURLINE(f)) {
inside = TRUE;
break;
}
j += PARAOF(p)->spacing;
} while (NEXTLINE(p));
if (!inside) {
/* Move it half-way into the window */
p = f->current;
j = LINEGAP(f);
do {
j += LINEOF(p)->height;
if (j + LINEGAP(f) > f->height / 2) break;
j += PARAOF(p)->spacing;
} while (PREVLINE(p));
f->top = p;
if ((f->type & FN_NORMAL) && !(f->type & FN_NOSCROLLBARS)) {
FindScrollPos(f);
SetScrollPos(f->parent, SB_VERT, f->vscroll, TRUE);
}
}
i = CalcLength (f, &(f->current)) - f->startx;
if (i >= 0 && i < f->width) return;
i += f->startx; /* Total length */
if (i < f->width) {
f->startx = 0;
} else {
/* Move it to the middle */
j = (i - (f->width / 3)) / BASEWIDTH(f);
f->startx = j * BASEWIDTH(f);
}
SetHorzScroll(f);
FillCPos(f, CURPARA(f), 0, -1);
}
void TakeCareOfThings (FILEOPTIONS *f, BOOL IncludingConversion)
{
if (SELTYPE(f) == SEL_SELECTION || IncludingConversion) {
if (SELPARA1(f) != NULL) TurnOffSelection(f);
SELPARA1(f) = SELPARA2(f) = NULL;
SELPOS1(f) = SELPOS2(f) = 0;
}
if (IncludingConversion) {
SELNOW(f) = FALSE;
CharInput(f, '\0');
}
}
/* 0 = white space, 1 = letter, 2 = kana, 3 = kanji */
static int GetCharType (KANJI ch)
{
if (ISASCII(ch)) {
if (ch <= ' ') return (0);
else return (1);
} else if (HIBYTE(ch) < 0x24) {
return (0);
} else {
if (HIBYTE(ch) == 0x24 || HIBYTE(ch) == 0x25) return (2);
else return (3);
}
}
/* 0 = space, 1 = kanji symbol, 2 = ASCII, 3 = kanji */
static int CategorizeChar (KANJI ch)
{
if (!ch || ch == ' ' || ch == 0x2121) return (0);
else if (ISASCII(ch)) return (2);
else if (HIBYTE(ch) < 0x30) return (1);
else return (3);
}
void ToggleInputMode (void)
{
int i;
i = SendMessage(global.tbhwnd, BM_GETSTATE, 0, ID_KANA);
SendMessage(global.tbhwnd, BM_SETSTATE, !i, ID_KANA);
SendMessage(global.tbhwnd, BM_SETSTATE, i, ID_ASCII);
//EnableToolbarButton(global.tbhwnd, ID_BOLD, i);
//EnableToolbarButton(global.tbhwnd, ID_ITALICS, i);
//EnableToolbarButton(global.tbhwnd, ID_REVERSE, !i);
if (global.mode == M_KANA) {
global.mode = M_ASCII;
StatusMessage("Switched to Text mode");
} else {
global.mode = M_KANA;
StatusMessage("Switched to Hiragana mode");
}
}
static ASCIIFONT *LoadASCIIFont (HDC hdc, FILEOPTIONS *f)
{
ASCIIFONT *CurFont;
CurFont = &DefAsciiFont;
if ((f->type & FN_NORMAL) && !global.draftview) {
SelectObject(hdc, CurFont->hfont);
} else {
SelectObject(hdc, SYSTEM_FONT);
}
SetMapperFlags(hdc, TRUE);
return (CurFont);
}
void RedrawFile (FILEOPTIONS *f, HDC hdc, int OffsetX, int OffsetY, RECT far *rp, BOOL ShowSpecial)
{
int i, j, k, l, r, RealWidth;
int lgap, cgap;
char ch;
KANJI c1, c2, c3;
BOOL insel;
HDC fhdc;
DWORD dimension;
BYTE far *cbufp;
ASCIIFONT *CurFont;
POSITION p;
RECT rect;
SetBkMode(hdc, TRANSPARENT);
if (rp == NULL) {
rp = ▭
GetClientRect(f->hwnd, &rect);
}
if (OffsetX != 0 || OffsetY != 0) SetWindowOrg(hdc, OffsetX, OffsetY);
/* Does it start in a selection? */
insel = FALSE;
if (SELPARA1(f) != NULL) insel = InSelection(f, f->top);
lgap = LINEGAP(f); if (lgap <= 0) lgap = 1;
CurFont = NULL;
fhdc = f->hdc;
f->hdc = hdc;
p = f->top;
j = LINEGAP(f); /* Vertical position */
do {
j += LINEOF(p)->height;
if (j - LINEOF(p)->height - lgap > rp->bottom) break;
if (j + lgap < rp->top) {
if (PARAOF(p) == SELPARA1(f) && LINEOF(p)->position <= SELPOS1(f) &&
(LINEOF(p)->position + LINEOF(p)->length) > SELPOS1(f))
insel = TRUE;
if (PARAOF(p) == SELPARA2(f)) {
if (LINEOF(p)->next == NULL) {
if (LINEOF(p)->position + LINEOF(p)->length >= SELPOS2(f))
insel = FALSE;
} else {
if (LINEOF(p)->position + LINEOF(p)->length > SELPOS2(f))
insel = FALSE;
}
}
j += PARAOF(p)->spacing;
continue;
}
/* Horizontal position */
i = BASEWIDTH(f) * LEFTMARGIN(p) - f->startx;
for (k = 0; k <= LINEOF(p)->length; k++) {
POSOF(p) = k;
cgap = CHARGAP(f);
c1 = (k <= 0) ? 0 : CHAROF(p,k-1);
c2 = CHAROF(p,k);
c3 = (k < LINEOF(p)->length - 1) ? CHAROF(p,k+1) : 0;
if (LINEOF(p)->next != NULL && k >= LINEOF(p)->length) {
if (CurFont == NULL) CurFont = LoadASCIIFont(hdc, f);
if (ShowSpecial && (f->type & FN_NORMAL) && c2 == '\n') {
ch = 0xab; /* << symbol */
TextOut(hdc, i, j - (global.draftview ? AVGHEIGHT : DefAsciiFont.textmetric.tmHeight), &ch, 1);
}
break;
}
if (SELPARA1(f) == NULL) {
insel = FALSE;
} else if (!insel && PARAOF(p) == SELPARA1(f) && &UNITOF(p,k) == &SELCHAR1(f)) {
insel = TRUE;
if ((k <= 0 && LINEOF(p)->length > 0) || (ISKANJI(c2) && c1 != '\t') || ISKANJI(c1)) {
PatBlt(hdc, i - CHARGAP(f), j - LINEOF(p)->height - lgap,
CHARGAP(f), LINEOF(p)->height + 2 * lgap, DSTINVERT);
}
} else if (insel && PARAOF(p) == SELPARA2(f) && &UNITOF(p,k) > &SELCHAR2(f)) {
insel = FALSE;
} else if (insel && k == 0 && LINEOF(p)->length > 0) {
PatBlt(hdc, i - CHARGAP(f), j - LINEOF(p)->height - lgap,
CHARGAP(f), LINEOF(p)->height + 2 * lgap, DSTINVERT);
} else if (insel && k > 0 && k < LINEOF(p)->length) {
if ((ISKANJI(c2) && c1 != '\t') || ISKANJI(c1)) {
PatBlt(hdc, i - f->leading + CHARGAP(f), j - LINEOF(p)->height - lgap,
f->leading - CHARGAP(f), LINEOF(p)->height + 2 * lgap, DSTINVERT);
}
}
if (k >= LINEOF(p)->length) {
if (insel && PARAOF(p) == SELPARA2(f) && &UNITOF(p,k) >= &SELCHAR2(f))
insel = FALSE;
if (PARAOF(p) == global.cpospara && LINEOF(p)->next == NULL) {
global.cpos[POS2ABS(p)].x = i;
global.cpos[POS2ABS(p)].y = j;
}
if (CurFont == NULL) CurFont = LoadASCIIFont(hdc, f);
if (ShowSpecial && (f->type & FN_NORMAL)) {
ch = 0xb6; /* Paragraph symbol */
TextOut(hdc, i, j - (global.draftview ? AVGHEIGHT : DefAsciiFont.textmetric.tmHeight), &ch, 1);
}
break;
}
if (j + lgap <= rp->top) continue;
if (!ISKANJI(c2)) cgap = 0;
dimension = GetDimension(f, p, i);
l = RealWidth = LOWORD(dimension); /* Char width */
if (c2 != '\t') {
if (ISKANJI(c2) || ISKANJI(c3)) l += f->leading;
}
if (i + RealWidth + cgap <= rp->left || i - cgap >= rp->right) {
i += l;
continue;
}
if (PARAOF(p) == global.cpospara) {
global.cpos[POS2ABS(p)].x = i;
global.cpos[POS2ABS(p)].y = j;
}
if (ISKANJI(c2)) {
r = Jis2Index(c2, f->basefont->holes);
if (r < 0) r = Jis2Index(BADKANJI, f->basefont->holes);
r = GetKanjiBitmap(f->basefont, r, &cbufp);
DisplayKanjiBitmap(hdc, i, j, f->basefont->width, f->basefont->height,
r, SRCCOPY, cbufp);
} else {
if (CurFont == NULL) CurFont = LoadASCIIFont(hdc, f);
switch (c2) {
case ' ':
ch = 0xb7; /* Space symbol */
if (ShowSpecial && (f->type & FN_NORMAL)) {
TextOut(hdc, i, j - (global.draftview ? AVGHEIGHT : DefAsciiFont.textmetric.tmHeight), &ch, 1);
}
break;
case '\t':
ch = 0xbb; /* >> symbol */
if (ShowSpecial && (f->type & FN_NORMAL)) {
int x, height;
height = global.draftview ? AVGHEIGHT : DefAsciiFont.textmetric.tmHeight;
x = j - height;
if (height < f->basefont->height) {
x -= (f->basefont->height - height) / 2;
}
TextOut(hdc, i, x, &ch, 1);
}
break;
case '\n':
ch = 0xab; /* << symbol */
if (ShowSpecial && (f->type & FN_NORMAL)) {
TextOut(hdc, i, j - (global.draftview ? AVGHEIGHT : DefAsciiFont.textmetric.tmHeight), &ch, 1);
}
break;
case '\r': break; /* Shouldn't happen */
default:
if (c2 < ' ') ch = DefAsciiFont.textmetric.tmDefaultChar;
else ch = c2;
TextOut(hdc, i, j - HIWORD(dimension), &ch, 1);
break;
}
}
if (insel) {
PatBlt(hdc, i, j - LINEOF(p)->height - lgap,
RealWidth + ((RealWidth < l) ? CHARGAP(f) : 0),
LINEOF(p)->height + 2 * lgap, DSTINVERT);
}
i += l;
}
j += PARAOF(p)->spacing;
} while (NEXTLINE(p));
f->hdc = fhdc;
}
LONG FAR PASCAL FileWinProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
int i, j, r;
int shift, ctrl;
int OldCharType, NewCharType;
HDC hdc;
PAINTSTRUCT ps;
POSITION p;
POINT point;
FILEOPTIONS *f;
BOOL scrolled, delay;
RECT cliprect;
/* Look for the current file */
f = (FILEOPTIONS *) GetWindowWord(hwnd, 0);
switch (message) {
case WM_CREATE:
SetWindowWord(hwnd, 0, (WORD) curfile);
return (0);
case WM_SIZE:
f->width = LOWORD(lParam);
f->height = HIWORD(lParam);
return (0);
case WM_COMMAND:
if (capturing) return (0);
switch (wParam) {
case IDM_EDITUNDO:
UndoOneStep(f);
return (0);
case IDM_EDITREDO:
RedoOneStep(f);
return (0);
case IDM_EDITCUT:
shift = TRUE; ctrl = FALSE; wParam = VK_DELETE;
goto KeyDown;
case IDM_EDITCOPY:
shift = FALSE; ctrl = TRUE; wParam = VK_INSERT;
goto KeyDown;
case IDM_EDITPASTE:
shift = TRUE; ctrl = FALSE; wParam = VK_INSERT;
goto KeyDown;
case IDM_EDITCLEAR:
shift = FALSE; ctrl = FALSE; wParam = VK_DELETE;
goto KeyDown;
case IDM_EDITSELECTALL: {
TakeCareOfThings(f, TRUE);
SELPARA1(f) = f->paragraph;
SELPOS1(f) = 0;
SELPARA2(f) = f->eof;
SELPOS2(f) = unitlen(f->eof->text);
if (SELPOS2(f) > 0) SELPOS2(f)--;
SELTYPE(f) = SEL_SELECTION;
SELNOW(f) = FALSE;
CURPARA(f) = f->eof;
CURLINE(f) = CURPARA(f)->lastline;
CURCHAR(f) = CURLINE(f)->length;
if (!FindCaret(f, TRUE)) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else {
FlipHighlight(f);
}
f->pseudo = f->cursor;
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
Triangles(f);
return (0);
}
case IDM_KANJICONVERT:
case IDM_KANJILCONVERT:
if (!ConvertOK(f)) {
MessageBeep(0);
return (0);
}
CharInput(f, '\x07');
if (SELNOW(f) || SELTYPE(f) == SEL_SELECTION) {
ConvertNow(f, FALSE);
} else {
SendMessage(global.convhwnd, WM_KEYDOWN,
(wParam == IDM_KANJILCONVERT) ? VK_LEFT : VK_RIGHT, 0L);
SendMessage(global.convhwnd, WM_KEYDOWN, VK_RETURN, 0L);
}
return (0);
case IDM_TOGGLEMODE:
if (f->type & FN_NOSWITCHING) {
MessageBeep(0);
return (0);
} else if (f->type & FN_EITHER) {
if (f->nr_bytes > 0) {
MessageBeep(0);
return (0);
}
}
TakeCareOfThings (f, TRUE);
ToggleInputMode();
if (!(f->type & FN_NORMAL)) {
HWND hwnd1;
hwnd1 = GetWindowWord(hwnd, sizeof(FILEOPTIONS *) + 2 * sizeof(WORD));
if (hwnd1 != NULL) InvalidateRect(hwnd1, NULL, FALSE);
}
return (0);
case IDM_KANJIINFO: {
KANJI ch = 0;
if (SELPARA1(f) != NULL && SELPARA2(f) != NULL && (SELPARA1(f) == SELPARA2(f))) {
for (i = SELPOS1(f); i <= SELPOS2(f); i++) {
ch = SELPARA1(f)->text[i].kanji & 0x7f7f;
if (ch >= 0x3021) break;
}
}
if (!ch || ch < 0x3021) {
ErrorMessage(global.hwnd, "You must select a KANJI or KANA.");
return (0);
}
SetKanjiInfoChar (ch);
curfile = f;
DialogBox (hInstance, "KanjiInfo", f->parent, KanjiInfoProc);
return (0);
}
case IDM_KANJIINPUT:
curfile = f;
DialogBox (hInstance, "KanjiInput", f->parent, JISInputProc);
return (0);
case IDM_KANJILOOKUP:
curfile = f;
DialogBox (hInstance, "KanjiLookup", f->parent, LookupProc);
return (0);
case IDM_KANJITABLE:
curfile = f;
DialogBox (hInstance, "JISTable", f->parent, JISTableDlgProc);
return (0);
}
return (0);
WM_CHAR_Case:
case WM_CHAR:
if (capturing) return (0);
shift = (GetKeyState(VK_SHIFT) < 0);
ctrl = (GetKeyState(VK_CONTROL) < 0);
switch (wParam) {
case '\r': TakeCareOfThings(f, TRUE);
CharInput(f, shift ? '\n' : '\r');
break;
case '\t': if (f->type & FN_NORMAL) {
CharInput(f, wParam);
}
break;
case '\b': CharInput(f, wParam);
break;
default: if (wParam > 26 /* ^Z */) {
CharInput (f, wParam);
//TakeCareOfThings(f, FALSE);
break;
}
j = 'A' + (wParam - 1);
i = DecodeKeyStroke(WM_CHAR, j, shift, ctrl);
if (i <= 0) {
MessageBeep(0); break;
}
switch (i) {
case IDM_KANJICONVERT:
case IDM_KANJILCONVERT:
if (shift) i = IDM_KANJILCONVERT;
SendMessage(hwnd, WM_COMMAND, i, 0L);
return (0);
case IDM_CONTINUESEARCH:
if (!(f->type & FN_NORMAL)) {
MessageBeep(0);
return (0);
}
SendMessage(global.hwnd, WM_COMMAND, i, 0L);
return (0);
case IDM_TOGGLEMODE: /* These ones can operate in an edit control */
case IDM_KANJIINFO:
case IDM_KANJIINPUT:
case IDM_KANJILOOKUP:
case IDM_KANJITABLE:
curfile = f;
SendMessage(hwnd, WM_COMMAND, i, 0L);
return (0);
default:
if (!(f->type & FN_NORMAL)) {
MessageBeep(0);
return (0);
}
j = GetMenuState(hmenu, i, MF_BYCOMMAND);
if (j & MF_GRAYED || j & MF_DISABLED) {
} else {
SendMessage(global.hwnd, WM_COMMAND, i, 0L);
return (0);
}
break;
}
break;
}
break;
case WM_KEYDOWN:
if (capturing) return (0);
/* Get the Key States */
shift = (GetKeyState(VK_SHIFT) < 0);
ctrl = (GetKeyState(VK_CONTROL) < 0);
KeyDown:
/* Is the caret currently in the window? */
if (!f->caret) MoveIntoWindow(f);
switch (wParam) {
case VK_HOME:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (ctrl) {
if (CURLINE(f) == f->paragraph->lines) return (0);
/* Ctrl-Home: Go to BOF */
CURPARA(f) = f->paragraph;
CURLINE(f) = f->paragraph->lines;
CURCHAR(f) = 0;
f->startx = 0;
SetHorzScroll(f);
if (TOPLINE(f) != f->paragraph->lines) {
if (shift) DropAnchor(f, f->current, f->cursor, -1);
SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0L);
f->pseudo = f->cursor;
} else {
FindCaret (f, TRUE);
f->pseudo = f->cursor;
if (shift) DropAnchor(f, f->current, f->cursor, -1);
if (shift) ExtendSelection(hwnd, f);
}
} else {
/* Home: Go to BOL */
if (CURCHAR(f) > 0) {
CURCHAR(f) = 0;
CURX(f) = PSEUDOX(f) = global.cpos[POS2ABS(f->current)].x;
if (shift) DropAnchor(f, f->current, f->cursor, -1);
if (!f->caret || f->startx > 0) {
f->startx = 0;
SetHorzScroll(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
}
}
break;
case VK_END:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (ctrl) {
if (CURLINE(f) == f->eof->lastline) return (0);
/* Ctrl-End: Go to EOF */
CURPARA(f) = f->eof;
CURLINE(f) = f->eof->lastline;
CURCHAR(f) = CURLINE(f)->length;
CURX(f) = CURLINE(f)->width - f->startx;
if (shift) DropAnchor(f, f->current, f->cursor, +1);
if (CURX(f) < 0 || CURX(f) >= f->width) MoveIntoWindow(f);
SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0L);
f->pseudo = f->cursor;
} else {
/* End: Go to EOL */
if (CURCHAR(f) < CURLINE(f)->length) {
CURCHAR(f) = CURLINE(f)->length;
PSEUDOX(f) = CURX(f) = CURLINE(f)->width - f->startx;
if (shift) DropAnchor(f, f->current, f->cursor, +1);
if (CURX(f) < 0 || CURX(f) >= f->width) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
}
}
break;
case VK_PRIOR:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (ctrl) {
/* Ctrl-PgUp: Go to BOS */
CtrlPgUp: if (CURPARA(f) == TOPPARA(f) && CURLINE(f) == TOPLINE(f))
return (0);
f->current = f->top;
CURY(f) = CURLINE(f)->height + LINEGAP(f);
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
MatchPseudo(f, TRUE, FALSE);
if (shift) {
DropAnchor(f, f->current, f->cursor, -1);
ExtendSelection(hwnd, f);
}
PSEUDOY(f) = CURY(f);
} else {
/* PgUp: Go to Previous page */
if (TOPPARA(f) == f->paragraph &&
TOPLINE(f) == f->paragraph->lines) goto CtrlPgUp;
p = f->top;
i = LINEGAP(f);
do {
i += LINEOF(p)->height;
if (i + LINEGAP(f) > f->height) break;
(f->vscroll)--;
i += PARAOF(p)->spacing;
} while (PREVLINE(p));
if ((f->type & FN_NORMAL) && !(f->type & FN_NOSCROLLBARS)) {
SetScrollPos(f->parent, SB_VERT, f->vscroll, TRUE);
}
f->top = p;
MatchPseudo(f, FALSE, TRUE);
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
MatchPseudo(f, TRUE, FALSE);
if (shift) DropAnchor(f, f->current, f->cursor, -1);
InvalidateRect(hwnd, NULL, TRUE);
break;
}
break;
case VK_NEXT:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (ctrl) {
/* Ctrl-PgDn: Go to EOS */
p = f->top;
j = LINEGAP(f); /* Vertical height */
scrolled = TRUE;
for (;;) {
j += LINEOF(p)->height;
if (j + LINEGAP(f) > f->height) break;
if (!NEXTLINE(p)) {
scrolled = FALSE;
break;
}
j += PARAOF(p)->spacing;
}
/* Move back to the previous line? */
if (scrolled) {
PREVLINE(p);
j -= LINEOF(p)->height + PARAOF(p)->spacing;
if (j < 0) j = -(PARAOF(p)->spacing - LINEGAP(f));
}
f->current = p;
CURY(f) = j;
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
MatchPseudo(f, TRUE, FALSE);
if (shift) {
DropAnchor(f, f->current, f->cursor, +1);
ExtendSelection(hwnd, f);
}
PSEUDOY(f) = CURY(f);
} else {
/* PgDn: Go to Next page */
p = f->top;
i = LINEGAP(f);
do {
i += LINEOF(p)->height;
if (i + LINEGAP(f) > f->height) break;
(f->vscroll)++;
i += PARAOF(p)->spacing;
} while (NEXTLINE(p));
f->top = p;
MatchPseudo(f, FALSE, FALSE);
if ((f->type & FN_NORMAL) && !(f->type & FN_NOSCROLLBARS)) {
SetScrollPos(f->parent, SB_VERT, f->vscroll, TRUE);
}
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
MatchPseudo(f, TRUE, FALSE);
if (shift) DropAnchor(f, f->current, f->cursor, +1);
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case VK_UP:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
i = CURLINE(f)->height;
if (!PREVLINE(f->current)) break;
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
CURY(f) -= i + CURPARA(f)->spacing;
MatchPseudo(f, TRUE, FALSE);
if (CURY(f) - CURLINE(f)->height - LINEGAP(f) < 0) {
DELAYCARET(TRUE);
SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0L);
RESTORECARET();
}
if (shift && !CaretDelayed) {
DropAnchor(f, f->current, f->cursor, -1);
ExtendSelection(hwnd, f);
}
PSEUDOY(f) = CURY(f);
break;
case VK_DOWN:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
i = CURPARA(f)->spacing;
if (!NEXTLINE(f->current)) break;
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
CURY(f) += CURLINE(f)->height + i;
MatchPseudo(f, TRUE, FALSE);
while (CURY(f) + LINEGAP(f) > f->height) {
DELAYCARET(TRUE);
SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0L);
RESTORECARET();
}
if (shift && !CaretDelayed) {
DropAnchor(f, f->current, f->cursor, +1);
ExtendSelection(hwnd, f);
}
PSEUDOY(f) = CURY(f);
break;
case VK_LEFT:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (ctrl) {
CURCHAR(f)--;
while (CURCHAR(f) < 0) {
if (!PREVLINE(f->current)) {
CURCHAR(f) = 0;
break;
}
CURCHAR(f) = CURLINE(f)->length - 1;
}
OldCharType = GetCharType(CHAROF(f->current, CURCHAR(f)));
/* Skip to the beginning */
do {
CURCHAR(f)--;
if (CURCHAR(f) < 0) break;
NewCharType = GetCharType(CHAROF(f->current, CURCHAR(f)));
if (OldCharType == 0) OldCharType = NewCharType;
} while (NewCharType == OldCharType);
CURCHAR(f)++;
if (CURCHAR(f) >= CURLINE(f)->length) {
if (NEXTLINE(f->current)) CURCHAR(f) = 0;
}
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
r = FindCaret(f, FALSE);
if (shift) DropAnchor(f, f->current, f->cursor, -1);
if (!r) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
f->pseudo = f->cursor;
} else {
if (CURCHAR(f) == 0) {
if (CURPARA(f)->prev == NULL && CURLINE(f)->prev == NULL)
return (0);
DELAYCARET(TRUE);
SendMessage(hwnd, WM_KEYDOWN, VK_UP, 0L);
RESTORECARET();
if (shift && CURLINE(f)->length > 0) {
CURCHAR(f) = CURLINE(f)->length - 1;
CURX(f) = global.cpos[POS2ABS(f->current)].x;
} else {
CURCHAR(f) = CURLINE(f)->length;
CURX(f) = CURLINE(f)->width - f->startx;
}
} else {
(CURCHAR(f))--;
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
CURX(f) = global.cpos[POS2ABS(f->current)].x;
}
if (shift) DropAnchor(f, f->current, f->cursor, -1);
if (CURX(f) < 0 || CURX(f) >= f->width) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
PSEUDOX(f) = CURX(f);
}
break;
case VK_RIGHT:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (!shift) {
TakeCareOfThings(f, TRUE); //SELNOW(f));
CharInput(f, '\0');
} else {
CharInput(f, '\0'); CharInput(f, '\0');
RecordAnchor(f, f->current, f->cursor);
}
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (ctrl) {
OldCharType = GetCharType(CHAROF(f->current, CURCHAR(f)));
do {
CURCHAR(f)++;
if (CURCHAR(f) >= CURLINE(f)->length) {
if (!NEXTLINE(f->current)) {
CURCHAR(f) = CURLINE(f)->length;
break;
}
CURCHAR(f) = 0;
}
NewCharType = GetCharType(CHAROF(f->current, CURCHAR(f)));
if (NewCharType == 0) /* Will not stop for white spaces */
OldCharType = NewCharType;
} while (NewCharType == OldCharType);
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
r = FindCaret(f, FALSE);
if (shift) DropAnchor(f, f->current, f->cursor, +1);
if (!r) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
f->pseudo = f->cursor;
} else {
if (CURCHAR(f) >= CURLINE(f)->length) {
if (CURPARA(f)->next == NULL && CURLINE(f)->next == NULL)
return (0);
DELAYCARET(TRUE);
SendMessage(hwnd, WM_KEYDOWN, VK_DOWN, 0L);
RESTORECARET();
if (shift && CURLINE(f)->length > 0) {
CURCHAR(f) = 1;
} else {
CURCHAR(f) = 0;
}
CURX(f) = global.cpos[POS2ABS(f->current)].x;
} else {
if (CURCHAR(f) + 1 >= CURLINE(f)->length) {
CURX(f) = CURLINE(f)->width - f->startx;
} else {
if (CURPARA(f) != global.cpospara) FillCPos(f, CURPARA(f), 0, -1);
CURX(f) = global.cpos[POS2ABS(f->current) + 1].x;
}
CURCHAR(f)++;
}
if (shift) DropAnchor(f, f->current, f->cursor, +1);
if (CURX(f) < 0 || CURX(f) >= f->width) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
} else if (shift) {
ExtendSelection(hwnd, f);
}
PSEUDOX(f) = CURX(f);
}
break;
case VK_INSERT:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (shift && !ctrl) InsertFromClipboard(f);
if (ctrl && !shift) CopyToClipboard(f);
break;
case VK_DELETE:
if (!f->caret) {
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (shift && !ctrl && SELPARA1(f) != NULL) CopyToClipboard(f);
CharInput(f, 127);
break;
default:
i = DecodeKeyStroke(WM_KEYDOWN, wParam, shift, ctrl);
if (i <= 0) {
if (wParam >= VK_F1 && wParam <= VK_F12) MessageBeep(0);
return (0);
}
switch (i) {
case IDM_KANJICONVERT:
case IDM_KANJILCONVERT:
if (shift) i = IDM_KANJILCONVERT;
SendMessage(hwnd, WM_COMMAND, i, 0L);
return (0);
case IDM_CONTINUESEARCH:
if (!(f->type & FN_NORMAL)) {
MessageBeep(0);
return (0);
}
SendMessage(global.hwnd, WM_COMMAND, i, 0L);
return (0);
case IDM_TOGGLEMODE: /* These ones can operate in an edit control */
case IDM_KANJIINFO:
case IDM_KANJIINPUT:
case IDM_KANJILOOKUP:
case IDM_KANJITABLE:
curfile = f;
SendMessage(hwnd, WM_COMMAND, i, 0L);
return (0);
default:
if (!(f->type & FN_NORMAL)) {
MessageBeep(0);
return (0);
}
j = GetMenuState(hmenu, i, MF_BYCOMMAND);
if (j & MF_GRAYED || j & MF_DISABLED) {
} else {
SendMessage(global.hwnd, WM_COMMAND, i, 0L);
return (0);
}
break;
}
break;
}
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
Triangles(f);
return (0);
case WM_VSCROLL:
if (capturing) return (0);
if (f->nr_lines - 1 <= 0) return (0);
switch (wParam) {
case SB_TOP:
CURPARA(f) = TOPPARA(f) = f->paragraph;
CURLINE(f) = TOPLINE(f) = f->paragraph->lines;
f->vscroll = 0;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_BOTTOM:
/* Go to the bottom */
TOPPARA(f) = f->eof;
TOPLINE(f) = f->eof->lastline;
f->vscroll = f->nr_lines;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_LINEUP:
if (!PREVLINE(f->top)) return (0);
(f->vscroll)--;
scrolled = TOPLINE(f)->height + TOPPARA(f)->spacing;
if (CaretDelayed) HideCaret(hwnd);
ScrollWindow(hwnd, 0, scrolled, NULL, NULL);
if (CaretDelayed) ShowCaret(hwnd);
ShiftCPos(f, 0, scrolled); /* The rest filled by WM_PAINT */
ChangeAnchor(0, scrolled);
break;
case SB_LINEDOWN:
scrolled = TOPLINE(f)->height + TOPPARA(f)->spacing;
if (!NEXTLINE(f->top)) return (0);
(f->vscroll)++;
if (CaretDelayed) HideCaret(hwnd);
ScrollWindow(hwnd, 0, -scrolled, NULL, NULL);
if (CaretDelayed) ShowCaret(hwnd);
ShiftCPos(f, 0, -scrolled); /* The rest filled by WM_PAINT */
ChangeAnchor(0, -scrolled);
break;
case SB_PAGEUP:
p = f->top;
i = LINEGAP(f);
do {
i += LINEOF(p)->height;
if (i + LINEGAP(f) > f->height) break;
(f->vscroll)--;
i += PARAOF(p)->spacing;
} while (PREVLINE(p));
f->top = p;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_PAGEDOWN:
p = f->top;
i = LINEGAP(f);
do {
i += LINEOF(p)->height;
if (i + LINEGAP(f) > f->height) break;
(f->vscroll)++;
i += PARAOF(p)->spacing;
} while (NEXTLINE(p));
f->top = p;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_THUMBPOSITION:
f->vscroll = LOWORD(lParam);
i = 0;
PARAOF(p) = f->paragraph;
LINEOF(p) = f->paragraph->lines;
do {
if (i >= f->vscroll) break;
i++;
} while (NEXTLINE(p));
f->top = p;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
default:
return (0);
}
if (f->vscroll < 0) f->vscroll = 0;
if (f->vscroll >= f->nr_lines) f->vscroll = f->nr_lines - 1;
if ((f->type & FN_NORMAL) && !(f->type & FN_NOSCROLLBARS)) {
SetScrollPos(f->parent, SB_VERT, f->vscroll, TRUE);
}
UpdateWindow(hwnd);
Triangles(f);
return (0);
case WM_HSCROLL:
if (capturing) return (0);
switch (wParam) {
case SB_TOP:
f->startx = 0;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_BOTTOM:
return (0);
case SB_PAGEUP:
i = f->width / BASEWIDTH(f);
f->startx -= (i/2) * BASEWIDTH(f);
if (f->startx < 0) f->startx = 0;
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_PAGEDOWN:
i = f->width / BASEWIDTH(f);
f->startx += (i/2) * BASEWIDTH(f);
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
case SB_LINEUP:
if (f->startx <= 0) return (0);
i = BASEWIDTH(f);
f->startx -= i;
ScrollWindow(hwnd, i, 0, NULL, NULL);
ShiftCPos(f, -i, 0);
break;
case SB_LINEDOWN:
i = BASEWIDTH(f);
f->startx += i;
ScrollWindow(hwnd, -i, 0, NULL, NULL);
ShiftCPos(f, i, 0);
break;
case SB_THUMBPOSITION:
f->startx = LOWORD(lParam) * BASEWIDTH(f);
InvalidateRect(hwnd, NULL, TRUE);
FillCPos(f, CURPARA(f), 0, -1);
break;
default:
return (0);
}
UpdateWindow(hwnd);
SetHorzScroll(f);
if ((f->type & FN_NORMAL) && RULER(f).hwnd != NULL) {
InvalidateRect(RULER(f).hwnd, NULL, TRUE);
UpdateWindow(RULER(f).hwnd);
}
return (0);
case WM_LBUTTONDBLCLK: {
int cat; /* 0 = space, 1 = kanji symbol, 2 = ASCII, 3 = kanji */
POSITION p1, p2, ptemp;
if (SELPARA1(f) != NULL) TurnOffSelection(f);
/* Categorize them */
cat = CategorizeChar(CHAROF(f->current, CURCHAR(f)));
if (cat == 0) return (0); /* No need to do anything */
p1 = p2 = f->current;
for (;;) {
ptemp = p2;
POSOF(ptemp)++;
if (POSOF(ptemp) >= LINEOF(ptemp)->length) {
if (LINEOF(ptemp)->next != NULL) {
LINEOF(ptemp) = LINEOF(ptemp)->next;
POSOF(ptemp) = 0;
} else {
break;
}
}
if (CategorizeChar(CHAROF(ptemp, POSOF(ptemp))) !=cat) break;
p2 = ptemp;
}
for (;;) {
ptemp = p1;
POSOF(ptemp)--;
if (POSOF(ptemp) < 0) {
if (LINEOF(ptemp)->prev != NULL) {
LINEOF(ptemp) = LINEOF(ptemp)->prev;
POSOF(ptemp) = LINEOF(ptemp)->length - 1;
} else {
break;
}
}
if (CategorizeChar(CHAROF(ptemp, POSOF(ptemp))) !=cat) break;
p1 = ptemp;
}
/* Select it */
SELPARA1(f) = SELPARA2(f) = CURPARA(f);
SELPOS1(f) = POS2ABS(p1); SELPOS2(f) = POS2ABS(p2);
SELTYPE(f) = SEL_SELECTION;
FlipHighlight(f);
f->current = p2;
CURCHAR(f)++;
if (FindCaret(f, FALSE))
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
else
DoCaret(f, 0, 0, FALSE);
return (0);
}
case WM_LBUTTONDOWN: {
int x, y;
if (!(f->type & FN_NORMAL)) {
DELAYCARET(TRUE);
SetFocus(hwnd);
RESTORECARET();
}
shift = (GetKeyState(VK_SHIFT) < 0);
TakeCareOfThings(f, TRUE); //shift);
/* Find where he clicked... */
x = PSEUDOX(f);
y = PSEUDOY(f);
PSEUDOX(f) = LOWORD(lParam);
PSEUDOY(f) = HIWORD(lParam);
if (shift) RecordAnchor(f, f->current, f->cursor);
if (!MatchPseudo(f, FALSE, TRUE)) {
PSEUDOX(f) = x;
PSEUDOY(f) = y;
} else {
MatchPseudo(f, TRUE, FALSE);
}
if (global.cpospara != CURPARA(f)) FillCPos(f, CURPARA(f), 0, -1);
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
if (shift) {
DropAnchor(f, f->current, f->cursor, 0);
ExtendSelection(hwnd, f);
}
LastSeen = f->cursor;
capturing = TRUE;
SetCapture(hwnd);
HideCaret(hwnd);
return (0);
}
case WM_MOUSEMOVE:
if (!capturing) return (0);
RecordAnchor(f, f->current, f->cursor);
/* Find where he moved to... */
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
if (point.x < 0) point.x = 0; if (point.x > f->width) point.x = f->width;
if (point.y < 0) point.y = 0; if (point.y > f->height) point.y = f->height;
PSEUDOX(f) = point.x;
PSEUDOY(f) = point.y;
MatchPseudo(f, FALSE, FALSE);
MatchPseudo(f, TRUE, FALSE);
point.x = CURX(f);
point.y = CURY(f);
/* Actually moved? */
if (point.x == LastSeen.x && point.y == LastSeen.y) return (0);
LastSeen = point;
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
DropAnchor(f, f->current, f->cursor, 0);
ExtendSelection(hwnd, f);
return (0);
case WM_LBUTTONUP:
if (!capturing) return (0);
ReleaseCapture();
capturing = FALSE;
Triangles(f);
if (global.cpospara != CURPARA(f)) FillCPos(f, CURPARA(f), 0, -1);
ShowCaret(hwnd);
return (0);
case WM_MOUSEACTIVATE:
/* It is always followed by a WM_SETFOCUS */
MouseActivated = TRUE;
if (!(f->type & FN_NORMAL)) return (0);
if (PrevWindow != hwnd && PrevWindow != f->parent && LOWORD(lParam) == HTCLIENT)
return (MA_ACTIVATEANDEAT);
else
return (MA_ACTIVATE);
case WM_PAINT:
/* Now draw the window */
Triangles(f);
HideCaret(hwnd);
hdc = BeginPaint(hwnd, &ps);
SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
cliprect = ps.rcPaint;
RedrawFile (f, hdc, 0, 0, &cliprect, global.showspecial);
if (!(f->type & FN_NORMAL) || f == global.active) {
if (FindCaret(f, FALSE))
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
else
DoCaret(f, 0, 0, FALSE);
}
EndPaint(hwnd, &ps);
ShowCaret(hwnd);
return (0);
case WM_SETFOCUS:
CreateCaret(hwnd, NULL, CARETWIDTH, f->basefont->height + LINEGAP(f));
f->caret = FALSE;
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
CharInput(f, '\0');
if (f->type & FN_NORMAL) {
for (f = fileoptions; f != NULL && f->hwnd != hwnd; f = f->next);
global.active = f;
for (f = fileoptions; f != NULL; f = f->next) {
if (f == global.active) continue;
TurnOffSelection(f);
}
} else if (!MouseActivated && GetParent((HWND) wParam) == GetParent(hwnd)) {
/* A dialog control activated by the TAB key */
i = unitlen(f->paragraph->text);
if (i > 0) {
TurnOffSelection(f);
SELPARA1(f) = SELPARA2(f) = f->paragraph;
SELPOS1(f) = 0; SELPOS2(f) = i - 1;
SELTYPE(f) = SEL_SELECTION;
FlipHighlight(f);
CURCHAR(f) = i;
if (!FindCaret(f, TRUE)) {
MoveIntoWindow(f);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
DoCaret(f, CURX(f), CURY(f) - CURLINE(f)->height, TRUE);
}
}
MouseActivated = FALSE;
return (0);
case WM_KILLFOCUS:
if (!(f->type & FN_NORMAL) && GetParent((HWND) wParam) == GetParent(hwnd)) {
/* A dialog control de-activated by TAB or mouse */
/* Make sure it returns to the beginning */
CURCHAR(f) = 0;
if (SELPARA1(f) != NULL) {
if (f->startx == 0) FlipHighlight(f);
SELPARA1(f) = SELPARA2(f) = NULL;
SELPOS1(f) = SELPOS2(f) = 0;
SELNOW(f) = FALSE;
SELTYPE(f) = SEL_SELECTION;
}
if (f->startx != 0) {
f->startx = 0;
InvalidateRect(hwnd, NULL, TRUE);
}
}
DoCaret(f, 0, 0, FALSE);
DestroyCaret();
return (0);
case WM_DESTROY: {
FILEOPTIONS *f1;
CloseFile(f);
/* Unlink it */
if (f->type & FN_NORMAL) {
if (fileoptions == f) {
fileoptions = f->next;
} else {
for (f1 = fileoptions; f1 != NULL && f1->next != f; f1 = f1->next);
if (f1 == NULL) {
ErrorMessage(global.hwnd, "Funny: cannot find FILEOPTIONS record to deallocate");
} else {
f1->next = f->next;
}
}
if (fileoptions == NULL) {
SwitchMenu(1); /* Minimal */
global.active = NULL;
}
}
FreeMem(f);
return (0);
}
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
LONG FAR PASCAL FileParentWinProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
FILEOPTIONS *f;
if (IsIconic(hwnd)) return(DefMDIChildProc(hwnd, message, wParam, lParam));
f = (FILEOPTIONS *) GetWindowWord(hwnd, 0);
switch (message) {
case WM_CREATE:
SetWindowWord(hwnd, 0, (WORD) curfile);
break;
case WM_SIZE:
if (RULER(f).hwnd) {
MoveWindow(RULER(f).hwnd, 0, 0,
LOWORD(lParam), RULERHEIGHT, TRUE);
}
if (f->hwnd != NULL) {
MoveWindow(f->hwnd, BORDERSPACE, BORDERSPACE + THERULER(f),
LOWORD(lParam) - BORDERSPACE,
HIWORD(lParam) - BORDERSPACE - THERULER(f), TRUE);
}
break;
case WM_KEYDOWN:
case WM_CHAR:
case WM_VSCROLL:
case WM_HSCROLL:
case WM_SETFOCUS:
case WM_KILLFOCUS:
SendMessage(f->hwnd, message, wParam, lParam);
break;
case WM_MDIACTIVATE:
if (!(f->type & FN_NORMAL)) return (0);
if (wParam) {
/* Save handle of window losing activity */
PrevWindow = HIWORD(lParam);
if (PrevWindow == NULL) PrevWindow = hwnd;
} else {
/* Deactivating window */
PrevWindow = NULL;
}
break;
case WM_SETCURSOR:
if (!(f->type & FN_NORMAL)) return (0);
PrevWindow = hwnd;
break;
case WM_CLOSE:
case WM_QUERYENDSESSION:
if (f->changed) {
char name[MAXLINELEN];
char buffer[MAXLINELEN];
if (!f->filename[0]) {
GetWindowText(hwnd, name, 50);
sprintf(buffer, "Close File: %s", name);
} else {
sprintf(buffer, "Close File: %s", f->filename);
}
MessageBeep(0);
if (IDOK != MessageBox (hwnd,
"You have made additional changes\n"
"to this file since you last saved it.\n"
"Closing the file now will lose these\n"
"changes!\n"
"\n"
"Do you REALLY want to close this\n"
"file and lose your changes?",
buffer, MB_ICONQUESTION | MB_OKCANCEL))
return (FALSE);
}
return (TRUE);
}
return (DefMDIChildProc(hwnd, message, wParam, lParam));
}
int CalcLineLength (FILEOPTIONS *f)
{
int margindots, linelen;
double charsize;
charsize = (double) (PRINTFONT->width + PRINTFONT->leading) * global.printscale;
charsize *= (double) global.resolution.x / (double) global.resolution.y;
margindots = (f->pagesetup.margins[0] + f->pagesetup.margins[1]) * global.resolution.x;
linelen = (int) floor(((global.paper[0] * global.resolution.x) - margindots) / charsize);
return (linelen);
}
FILEOPTIONS *NewFile (int type, BOOL allocate)
{
FILEOPTIONS *f;
PARAGRAPH far *p;
ONELINE far *lp;
f = (FILEOPTIONS *) MemAlloc(sizeof(FILEOPTIONS));
if (f == NULL) return (NULL);
if (type & FN_NORMAL) {
f->next = fileoptions;
fileoptions = f;
f->leading = global.leading;
f->spacing = global.spacing;
f->basefont = BASEFONT;
f->pagesetup = global.pagesetup;
f->linelen = CalcLineLength(f);
} else {
f->next = NULL;
f->leading = SYSFONT->leading;
f->spacing = SYSFONT->spacing;
f->basefont = SYSFONT;
f->linelen = 1000; /* The caller should set it later */
}
curfile = f;
f->nr_bytes = 0L;
f->fileformat = FF_NORMAL;
f->type = type;
f->undo = f->undotail = f->redo = f->redotail = NULL;
f->undolevels = 0;
/* Allocate one paragraph and one line */
if (!allocate) {
f->paragraph = f->eof = NULL;
TOPPARA(f) = CURPARA(f) = NULL;
TOPLINE(f) = CURLINE(f) = NULL;
CURCHAR(f) = 0;
f->nr_lines = 0;
} else {
f->paragraph = f->eof = p = StructAlloc(PARAGRAPH);
p->prev = p->next = NULL;
p->leftindent = p->firstindent = p->rightindent = 0;
p->spacing = f->spacing;
p->spacemulti = 100;
p->text = (UNIT far *) BlockAlloc(FIRSTBLOCKSIZE);
p->textsize = FIRSTBLOCKSIZE / sizeof(UNIT);
p->text[0].kanji = 0;
lp = p->lines = p->lastline = StructAlloc(ONELINE);
lp->next = lp->prev = NULL;
lp->position = 0;
lp->height = f->basefont->height;
lp->length = lp->width = 0;
TOPPARA(f) = CURPARA(f) = f->paragraph;
TOPLINE(f) = CURLINE(f) = f->paragraph->lines;
CURCHAR(f) = 0;
f->nr_lines = 1;
}
CURX(f) = PSEUDOX(f) = 0;
CURY(f) = PSEUDOY(f) = f->basefont->height + 2;
f->caret = FALSE;
f->changed = FALSE;
f->vscroll = f->hscroll = 0;
f->hdc = NULL;
f->hwnd = f->parent = NULL;
f->startx = 0;
f->relaxmargin = global.relaxmargin;
RULER(f).hwnd = NULL;
RULER(f).smallticks = AVGHEIGHT / 3;
if (RULER(f).smallticks <= 0) RULER(f).smallticks = 1;
RULER(f).bigticks = 2 * RULER(f).smallticks;
RULER(f).upperrow = 3 * RULER(f).smallticks - 1;
RULER(f).lowerrow = RULERHEIGHT - 1;
RULER(f).middlerow = (RULERHEIGHT + RULER(f).upperrow) / 2;
RULER(f).pointer = (f->basefont->width + f->leading) / 3;
if (RULER(f).pointer > AVGWIDTH) RULER(f).pointer = AVGWIDTH;
RULER(f).startx = 0;
SELNOW(f) = FALSE;
SELPARA1(f) = SELPARA2(f) = NULL;
SELPOS1(f) = SELPOS2(f) = 0;
SELTYPE(f) = SEL_CONVERSION;
/* left/right/first positions set in first call in WM_PAINT */
return (f);
}
void ShowFileWindow(char *title, FILEOPTIONS *f)
{
int RulerHeight;
MDICREATESTRUCT mdicreate;
RECT rect;
/* Switch to the full menu */
SwitchMenu(0);
/* Create the MDI child window */
GetClientRect(global.clienthwnd, &rect);
mdicreate.szClass = "JWP File Parent";
mdicreate.szTitle = title;
mdicreate.hOwner = hInstance;
mdicreate.x = mdicreate.y = 0;
mdicreate.cx = rect.right;
mdicreate.cy = rect.bottom;
if (f->type & FN_NOSCROLLBARS) {
mdicreate.style = WS_MAXIMIZE;
} else {
mdicreate.style = WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE;
}
mdicreate.lParam = NULL;
/* Create the parent window */
//ShowWindow(global.clienthwnd, SW_HIDE);
//SendMessage(global.clienthwnd, WM_SETREDRAW, FALSE, 0L);
curfile = f;
f->hwnd = f->parent = NULL;
f->parent = SendMessage (global.clienthwnd, WM_MDICREATE, 0,
(LONG) (LPMDICREATESTRUCT) &mdicreate);
if (f->type & FN_NOSCROLLBARS) {
SetScrollRange(f->parent, SB_VERT, 0,
(f->nr_lines - 1 > 0) ? f->nr_lines : 1, FALSE);
SetScrollRange(f->parent, SB_HORZ, 0, f->linelen, FALSE);
SetScrollPos(f->parent, SB_VERT, 0, TRUE);
SetScrollPos(f->parent, SB_HORZ, 0, TRUE);
}
GetClientRect(f->parent, &rect);
/* Now create the child window */
if (global.showruler) {
DisplayRuler(f, TRUE);
RulerHeight = RULERHEIGHT;
} else {
RulerHeight = 0;
}
f->hwnd = CreateWindow("JWP File", NULL, WS_CHILDWINDOW | WS_VISIBLE,
BORDERSPACE, BORDERSPACE + RulerHeight,
rect.right - BORDERSPACE,
rect.bottom - BORDERSPACE - RulerHeight,
f->parent, 0, hInstance, NULL);
//SendMessage(global.clienthwnd, WM_SETREDRAW, TRUE, 0L);
//ShowWindow(global.clienthwnd, SW_SHOW);
ShowWindow(f->parent, SW_SHOW);
ShowWindow(f->hwnd, SW_SHOW);
FillCPos(f, CURPARA(f), 0, -1);
SetFocus(f->hwnd);
}